// 编译指令： g++ -o ./output/sdb Field.cpp Table.cpp Database.cpp main1.cpp

#include "Database.h"

#include <filesystem>
#include <iostream>
#include <fstream>
#include <vector>
#include <deque>
#include <string>
#include <unordered_map>

//终端颜色控制字符
#define CYN "\e[0;36m" // 蓝色
#define RED "\e[0;31m" // 红色
#define NC "\e[0m"     // 恢复回白色

//全局变量初始化 

Database *database;
std::unordered_map<std::string, int> methods = {
  {"info", 1},{"create", 2},{"drop", 3},{"use", 4},{"insert", 5},
  {"delete", 6},{"select", 7},{"list", 8},{"quit", 9}
};
int status = 0; //0表示数据库模式，1表示数据表模式；

//识别命令

// 数据库模式下
int limited_func(std::deque<std::string> input){
	if (input.size() == 0) return 0;
	switch(methods[input[0]]){
		case 1: { //info
			//......
			break;
		}
		case 2: { //create
			if(input.size() > 2){
			    std::ifstream checkfile(input[2] + ".sdb");
			    if(checkfile.is_open()){
			   	    checkfile.close();
			   	    std::cout << "This database is already exist" << std::endl;
			    }
			    else{
			   		std::ofstream newfile;
				    newfile.open(input[2] + ".sdb", std::ios::out);
					newfile << 0;
					newfile.close();
			    }
			}
			break;
		}
		case 3: { //drop
			if (input.size() > 2) {
				std::filesystem::remove(input[2] + ".sdb");
			}
			break;
		}
		case 4: { //use
		    if(input.size() > 1){
				database = new Database(input[1]);
		    	status = 1;
			}
		    break;
		}
		case 8: { //list
	    	//......
	    	break;
		}
	    case 9: { //quit procedure
			return 1;
			break;
		}
		default: {
			std::cout<<"Please check the format of your input"<<std::endl;
			break;
		}
	}
	return 0;
}

// 数据表模式下
int full_func(std::deque<std::string> input){
	if (input.size() == 0) return 0;
	switch(methods[input[0]]){
		case 1: { //info
			if (input.size() == 1) {
				database->info();
			} else if (input[1] == "table") {
				database->table_info(input[2]);
			} //......
			else std::cout<<"Please select a database first"<<std::endl;
			break;
		}
		case 2: { //create
			if(input[1] == "database" && input.size() > 2){ // 按道理说数据表模式下不应该再能创建数据库的，不过没影响
			    std::ifstream checkfile(input[2] + ".sdb");
			    if(checkfile.is_open()){
			    	checkfile.close();
			    	std::cout << "This database is already exist" << std::endl;
			    }
			    else{
			    	std::ofstream newfile;
				    newfile.open(input[2] + ".sdb", std::ios::out);
					newfile << 0;
					newfile.close();
			    }
			}
			else if(input[1] == "table"){
				if (input[3].front() == '(' && input[input.size()-1].back() == ')'){
					input[3].erase(0, 1);
					input[input.size()-1].pop_back();
					std::string fields_set = "\0";
					for(int i = 3;i < input.size();i++){
						fields_set += input[i];
						if(i != input.size() - 1) fields_set += " ";
					}
					database->create_table(input[2], fields_set);
				}
				else std::cout<<"Please check whether you have entered the create command correctly"<<std::endl;
			}
			break;
		}
		case 3: { //drop
		    if(input[1] == "table") database->drop_table(input[2]);
		    else if(input[1] == "database"){
		    	std::filesystem::remove(input[2] + ".sdb");
			}
		    break;
		}
		case 4: { //use
		    if(input.size() > 1){
				database->write_back();
				delete database;
				database = new Database(input[1]);
			}
		    break;
		}
		case 5: { //insert
		    if(input[1] == "into" && input[3] == "set"){
				std::string fields = "\0";
				for(int i = 4;i < input.size();i++){
					fields += input[i];
					if(i != input.size() - 1) fields += " ";
				}
				database->insert_record(input[2], fields);
			}
			else std::cout<<"Please check whether you have entered the insert command correctly"<<std::endl;
			break;
		}
		case 6: { //delete
			if(input[1] == "from"){
				std::string fields = "\0";
				for(int i = 4;i < input.size();i++){
					fields += input[i];
					if(i != input.size() - 1) fields += " ";
				}
				if(fields != "\0" && fields != "*") database->delete_record(input[2], fields);
				else database->delete_record(input[2]); // delete all
			}
			else std::cout<<"Please check whether you have entered the delete command correctly"<<std::endl;
			break;
		}
		case 7: { //select
			std::string show_fields = "\0";
			std::string filters = "\0";
			std::string order = "\0";
			int i = 1;
			for(;i < input.size();i++){
				show_fields += input[i];
				if(input[i+1] == "from") {
					i += 2;
					break; //please ensure that there has a 'from' in input
			    }
				show_fields += " "; 
			}
			std::string table_name = input[i];
			i += 2;

			for(;i < input.size();i++){
				filters += input[i];
				if(input[i+1] == "order") {
					i += 3;
					break; //please ensure that there has a 'order by' in input 
			    }
				filters += " ";
			}
			for(;i < input.size();i++){
				order += input[i];
				if(i != input.size() - 1) order += " ";
			}
			
			if(show_fields != "*"){
				if(order != "\0") database->select_record(table_name, show_fields, filters, order);
				else database->select_record(table_name, show_fields, filters);
			}
			else if(show_fields != "\0"){
				if(order != "\0") database->select_record(table_name, "*", filters, order);
				else database->select_record(table_name, "*", filters);
			}
			break;
		}
		case 8: { //list
	    	//......
	    	break;
		}
		case 9: { //quit database
			database->write_back();
			status = 0;
			break;
		}
		default: {
			std::cout<<"Please check the format of your input"<<std::endl;
			break;
		}
	}
	return 0;
}

int main(){
	std::cout << "Welcome to the database system." << std::endl;
	std::cout << CYN "(no database used) > " NC;
	
	while(1){
		std::deque<std::string> input;
		std::string word;
		
		while(std::cin >> word){
			if(word.back() == ';') {
			   word.pop_back();
			   if(!word.empty()) input.push_back(word);
			   break;	
			}
			else{
				input.push_back(word);
			}
		}
		int should_exit;
		
		if(status == 0) should_exit = limited_func(input); // 数据库模式下
		else should_exit = full_func(input); // 数据表模式下
		
		if(should_exit == 1) break;

		if(status == 0) std::cout << CYN "(no database used) > " NC;
		else std::cout << CYN "(" << database->name << ") > " NC;
	}
	
	return 0;
}